#pragma once
#include <vector>
#include <queue>
#include "thread.hpp"
#include "lockGuard.hpp"
#include "task.hpp"
// 基于单例模式的线程池设计
const static int NUM = 5;
template <class T>
class threadPool
{
private:
    // 因为只能有一个线程池实例所以不能让用户自己构造线程池
    threadPool(int num = NUM) : _num(num)
    {
        pthread_mutex_init(&_lock, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }
    threadPool(const threadPool<T> &tp) = delete;
    void operator=(const threadPool<T> &tp) = delete;

public:
    static threadPool<T> *getInstance()
    {
        if (instance == nullptr) // 减少加锁的次数
        {
            xjc::lockGuard guard(&instanceLock);
            if (instance == nullptr)
            {
                instance = new threadPool<T>();
                instance->init();
                instance->start();
            }
        }
        return instance;
    }
    pthread_mutex_t *getLock()
    {
        return &_lock;
    }
    bool isEmpty()
    {
        return _tasks.empty();
    }
    void threadWait()
    {
        pthread_cond_wait(&_cond, &_lock);
    }
    T popTask()
    {
        //xjc::lockGuard guard(&_lock);
        T t = _tasks.front();
        _tasks.pop();
        return t;
    }
    static void *threadRoutine(void *args)
    {
        threadPool<T> *tp = static_cast<threadPool<T> *>(args);
        while (true)
        {
            T t;
            {
                xjc::lockGuard guard(tp->getLock());
                while (tp->isEmpty())
                {
                    // 任务队列为空就让线程等待
                    tp->threadWait();
                }
                t = tp->popTask();
            }
            // 执行任务
            std::string s = t();
            std::cout << "thread handle done,result: " << s << std::endl;
        }
    }
    void init()
    {
        //std::cout<<_num;
        for (int i = 0; i < _num; i++)
        {
            _threads.push_back(thread(i, threadRoutine, this));
        }
    }
    void start()
    {
        for (int i = 0; i < _threads.size(); i++)
        {
            _threads[i].run();
        }
    }
    void threadWakeup()
    {
        pthread_cond_signal(&_cond);
    }
    void pushTask(const T &t)
    {
        xjc::lockGuard guard(&_lock);
        _tasks.push(t);
        threadWakeup();
    }
    void check()
    {
        std::cout<<_threads.size();
        for (int i=0;i<_threads.size();i++)
        {
            std::cout << _threads[i].getName() << "runing..." << std::endl;
        }
    }
    ~threadPool()
    {
        for (int i = 0; i < _threads.size(); i++)
        {
            _threads[i].join();
        }
        pthread_mutex_destroy(&_lock);
        pthread_cond_destroy(&_cond);
    }

private:
    std::vector<thread> _threads; // 用vector管理各个线程
    int _num;                     // 线程数量
    std::queue<task> _tasks;      // 任务队列
    pthread_mutex_t _lock;
    pthread_cond_t _cond;
    static threadPool<T> *instance;
    static pthread_mutex_t instanceLock;
};

template <class T>
threadPool<T> *threadPool<T>::instance = nullptr;

template <class T>
pthread_mutex_t threadPool<T>::instanceLock = PTHREAD_MUTEX_INITIALIZER;